package lesson2.example5;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.lang.reflect.Proxy;

// 一个继承了Annotation的接口
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@interface MyClassAnnotation {
    String uri();
    String desc();
}


@MyClassAnnotation(
	desc = "TestRuntimeAnnotation", 
	uri = "lesson2.example5.TestRuntimeAnnotation"
)
public class TestRuntimeAnnotation {

	public static void main(String[] args) throws Exception {
		test1();
		test2();
	}
	
	/*
	 * 
	 * 调用desc()后返回TestRuntimeAnnotation
	 * 调用uri后返回lesson2.example5.TestRuntimeAnnotation
	 * 在虚拟机中通过RuntimeVisibleAnnotations等属性保存对应关系，通过Map来保存
	 *   desc=TestRuntimeAnnotation
	 *   uri=lesson2.example5.TestRuntimeAnnotation
	 *   
	 * 虚拟机中关于类元信息的获取可以通过反射方式，那么注解信息同样也可以通过反射方式获取，然后就是
	 * 调用对应的方法获取相关的值了，由于注解类其实是一个接口，可以针对接口进行代理的是JDK动态代理
	 * 
	 */

	public static void test1() {
		// 通过反射从类元信息中获取注解相关信息
		Class<TestRuntimeAnnotation> clazz = TestRuntimeAnnotation.class;
		MyClassAnnotation myClassAnnotation = clazz.getAnnotation(MyClassAnnotation.class);
		
		// 根据配置在TestRuntimeAnnotation类上注解的信息进行操作...
		System.out.println(myClassAnnotation.desc());
		System.out.println(myClassAnnotation.uri());
		
		
	}

	public static void test2() {
		// 通过动态代理实现方法调用
		MyClassAnnotation m = (MyClassAnnotation) Proxy.newProxyInstance(
				MyClassAnnotation.class.getClassLoader(),
				new Class<?>[] { MyClassAnnotation.class }, 
				new AnnotationInvocationHandler());

		// 调用desc()、uri()等方法其实是调用代理对象的AnnotationInvocationHandler
		System.out.println(m.desc());
		System.out.println(m.uri());
	}
}






